home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Languguage OS 2
/
Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO
/
language
/
asa
/
user.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-10-23
|
57KB
|
1,967 lines
/***********************************************************************
* Lester Ingber (copyright) (c)
* See COPYING License in this directory
* Date 1 Jan 93
***********************************************************************/
#define USER_ID \
"/* $Id: user.c,v 4.2 1994/10/23 23:35:13 ingber Exp ingber $ */"
#include "user.h"
#if SELF_OPTIMIZE
#else
/***********************************************************************
* main
* This is a sample calling program to optimize using ASA
***********************************************************************/
#if HAVE_ANSI
#if ASA_LIB
int
asa_main ()
#else
int
main (int argc, char **argv)
#endif
#else
#if ASA_LIB
int
asa_main ()
#else
int
main (argc, argv)
int argc;
char **argv;
#endif
#endif
{
int *exit_code;
#if ASA_LIB
#else
int compile_cnt;
#endif
#if ASA_SAMPLE
#if ASA_TEMPLATE
FILE *ptr_asa;
#endif
#endif
/* pointer to array storage for asa arguments */
double *parameter_lower_bound, *parameter_upper_bound, *cost_parameters,
*cost_tangents, *cost_curvature;
double cost_value;
/* the number of parameters to optimize */
ALLOC_INT *parameter_dimension;
/* pointer to array storage for parameter type flags */
int *parameter_int_real;
/* valid flag for cost function */
int *cost_flag;
USER_DEFINES *USER_OPTIONS;
#if OPTIONS_FILE
FILE *ptr_options;
char read_option[80];
int read_int;
LONG_INT read_long;
double read_double;
#endif
#if ASA_TEMPLATE
#if USER_ASA_OUT
int n_asa, n_trajectory, index;
#if HAVE_ANSI
char asa_file[8] = "asa_x_y";
#else
char asa_file[8];
asa_file[0] = asa_file[2] = 'a';
asa_file[1] = 's';
asa_file[3] = asa_file[5] = '_';
asa_file[4] = 'x';
asa_file[6] = 'y';
asa_file[7] = '\0';
#endif /* HAVE_ANSI */
#endif /* USER_ASA_OUT */
#endif /* ASA_TEMPLATE */
/* open the output file */
ptr_out = fopen ("user_out", "w");
/* use this instead if you want output to stdout */
#if FALSE
ptr_out = stdout;
#endif
fprintf (ptr_out, "%s\n\n", USER_ID);
#if ASA_LIB
#else
/* print out compile options set by user in Makefile */
if (argc > 1)
{
fprintf (ptr_out, "CC = %s\n", argv[1]);
for (compile_cnt = 2; compile_cnt < argc; ++compile_cnt)
{
fprintf (ptr_out, "\t%s\n", argv[compile_cnt]);
}
fprintf (ptr_out, "\n");
}
#endif
#if TIME_CALC
/* print starting time */
print_time ("start", ptr_out);
#endif
fflush (ptr_out);
#if OPTIONAL_DATA
/* Set memory to that required for use. */
if ((USER_OPTIONS->asa_data =
(double *) calloc (2, sizeof (double))) == NULL)
exit (9);
/* Use asa_data[0] as flag, e.g., if used with SELF_OPTIMIZE. */
USER_OPTIONS->asa_data[0] = 1.0;
#endif
initialize_rng ();
/* Initialize the users parameters, allocating space, etc.
Note that the default is to have asa generate the initial
cost_parameters that satisfy the user's constraints. */
if ((parameter_dimension =
(ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL)
exit (9);
if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
#if SELF_OPTIMIZE
#else
if ((USER_OPTIONS =
(USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL)
exit (9);
#if OPTIONS_FILE
ptr_options = fopen ("asa_opt", "r");
#if INT_LONG
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
USER_OPTIONS->LIMIT_ACCEPTANCES = read_long;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
USER_OPTIONS->LIMIT_GENERATED = read_long;
#else
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->LIMIT_ACCEPTANCES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->LIMIT_GENERATED = read_int;
#endif
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->COST_PRECISION = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->MAXIMUM_COST_REPEAT = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->NUMBER_COST_SAMPLES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->TEMPERATURE_RATIO_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->COST_PARAMETER_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->TEMPERATURE_ANNEAL_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->USER_INITIAL_COST_TEMP = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->INCLUDE_INTEGER_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->USER_INITIAL_PARAMETERS = read_int;
#if INT_ALLOC
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_int;
#else
#if INT_LONG
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_long;
#else
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_int;
#endif
#endif
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->INITIAL_PARAMETER_TEMPERATURE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->RATIO_TEMPERATURE_SCALES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->TESTING_FREQUENCY_MODULUS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->ACTIVATE_REANNEAL = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->REANNEAL_RESCALE = read_double;
fscanf (ptr_options, "%s", read_option);
#if INT_LONG
fscanf (ptr_options, "%ld", &read_long);
#else
fscanf (ptr_options, "%d", &read_long);
#endif
USER_OPTIONS->MAXIMUM_REANNEAL_INDEX = read_long;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
USER_OPTIONS->DELTA_X = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->DELTA_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->USER_TANGENTS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->CURVATURE_0 = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->QUENCH_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
USER_OPTIONS->QUENCH_COST = read_int;
fclose (ptr_options);
#else /* OPTIONS_FILE */
/* USER_OPTIONS->LIMIT_ACCEPTANCES = 10000; */
USER_OPTIONS->LIMIT_ACCEPTANCES = 1000;
USER_OPTIONS->LIMIT_GENERATED = 99999;
USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = 1000;
/* USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = 1.0E-6; */
USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = 1.0E-4;
USER_OPTIONS->COST_PRECISION = 1.0E-18;
USER_OPTIONS->MAXIMUM_COST_REPEAT = 5;
USER_OPTIONS->NUMBER_COST_SAMPLES = 5;
USER_OPTIONS->TEMPERATURE_RATIO_SCALE = 1.0E-5;
USER_OPTIONS->COST_PARAMETER_SCALE = 1.0;
USER_OPTIONS->TEMPERATURE_ANNEAL_SCALE = 100.0;
USER_OPTIONS->USER_INITIAL_COST_TEMP = FALSE;
USER_OPTIONS->INCLUDE_INTEGER_PARAMETERS = FALSE;
USER_OPTIONS->USER_INITIAL_PARAMETERS = FALSE;
USER_OPTIONS->SEQUENTIAL_PARAMETERS = -1;
USER_OPTIONS->INITIAL_PARAMETER_TEMPERATURE = 1.0;
USER_OPTIONS->RATIO_TEMPERATURE_SCALES = FALSE;
USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS = FALSE;
USER_OPTIONS->TESTING_FREQUENCY_MODULUS = 100;
USER_OPTIONS->ACTIVATE_REANNEAL = TRUE;
USER_OPTIONS->REANNEAL_RESCALE = 10.0;
USER_OPTIONS->MAXIMUM_REANNEAL_INDEX = 50000;
USER_OPTIONS->DELTA_X = 0.001;
USER_OPTIONS->DELTA_PARAMETERS = FALSE;
USER_OPTIONS->USER_TANGENTS = FALSE;
USER_OPTIONS->CURVATURE_0 = FALSE;
USER_OPTIONS->QUENCH_PARAMETERS = FALSE;
USER_OPTIONS->QUENCH_COST = FALSE;
#endif /* OPTIONS_FILE */
#endif /* SELF_OPTIMIZE */
/* ALLOCATE STORAGE */
#if USER_ASA_OUT
if ((USER_OPTIONS->asa_out_file =
(char *) calloc (80, sizeof (char))
) == NULL)
exit (9);
#endif
#if ASA_TEST
/* the number of parameters for the cost function */
*parameter_dimension = 4;
/* end ASA_TEST */
#else /* MY_COST */
/* the number of parameters for the cost function */
#endif /* MY_COST */
#if ASA_SAMPLE
#if ASA_TEMPLATE
*parameter_dimension = 2;
USER_OPTIONS->QUENCH_PARAMETERS = TRUE;
USER_OPTIONS->QUENCH_COST = TRUE;
USER_OPTIONS->USER_TANGENTS = TRUE;
#endif
#endif
#if ASA_TEMPLATE
#if ASA_PARALLEL
USER_OPTIONS->gener_block = 100;
USER_OPTIONS->gener_block_max = 512;
USER_OPTIONS->gener_mov_avr = 3;
#endif
#endif
/* allocate parameter minimum space */
if ((parameter_lower_bound =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
/* allocate parameter maximum space */
if ((parameter_upper_bound =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
/* allocate parameter initial values; the parameter final values
will be stored here later */
if ((cost_parameters =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
/* allocate the parameter types, real or integer */
if ((parameter_int_real =
(int *) calloc (*parameter_dimension, sizeof (int))
) == NULL)
exit (9);
/* allocate space for parameter cost_tangents -
used for reannealing */
if ((cost_tangents =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if (USER_OPTIONS->CURVATURE_0 == FALSE || USER_OPTIONS->CURVATURE_0 == -1)
{
/* allocate space for parameter cost_curvatures/covariance */
if ((cost_curvature =
(double *) calloc ((*parameter_dimension) *
(*parameter_dimension),
sizeof (double))) == NULL)
exit (9);
}
else
{
cost_curvature = (double *) NULL;
}
#if USER_COST_SCHEDULE
USER_OPTIONS->cost_schedule = user_cost_schedule;
#endif
#if USER_REANNEAL_FUNCTION
USER_OPTIONS->reanneal_function = user_reanneal;
#endif
initialize_parameters (cost_parameters,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
USER_OPTIONS);
/* optimize the cost_function, returning the results in
cost_value and cost_parameters */
#if ASA_TEMPLATE
#if USER_ASA_OUT
/* multiple asa() quenched calls + multiple asa_out files
(To get longer quenched runs, decrease SMALL_FLOAT.) */
for (n_asa = 1; n_asa <= *parameter_dimension; n_asa++)
{
asa_file[4] = 'A' + n_asa - 1;
if (USER_OPTIONS->QUENCH_COST == TRUE)
USER_OPTIONS->user_quench_cost_scale[0] = (double) n_asa;
if (USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_quench_param_scale[index] =
(double) n_asa;
for (n_trajectory = 0; n_trajectory < 3; ++n_trajectory)
{
asa_file[6] = 'a' + n_trajectory;
strcpy (USER_OPTIONS->asa_out_file, asa_file);
#endif
#endif
cost_value =
asa (cost_function,
randflt,
cost_parameters,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
cost_flag,
exit_code,
USER_OPTIONS);
#if TIME_CALC
/* print ending time */
print_time ("end", ptr_out);
#endif
#if ASA_TEMPLATE
#if USER_ASA_OUT
}
}
#endif
#endif
#if ASA_SAMPLE
#if ASA_TEMPLATE
#if USER_ASA_OUT
ptr_asa = fopen (USER_OPTIONS->asa_out_file, "r");
#else
ptr_asa = fopen ("asa_out", "r");
#endif
sample (ptr_out, ptr_asa);
#endif
#endif
/* close all files */
fclose (ptr_out);
#if OPTIONAL_DATA
free (USER_OPTIONS->asa_data);
#endif
#if USER_ASA_OUT
free (USER_OPTIONS->asa_out_file);
#endif
#if ASA_SAMPLE
free (USER_OPTIONS->bias_generated);
#endif
if (USER_OPTIONS->CURVATURE_0 == FALSE || USER_OPTIONS->CURVATURE_0 == -1)
free (cost_curvature);
if (USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS == TRUE)
free (USER_OPTIONS->user_parameter_temperature);
if (USER_OPTIONS->USER_INITIAL_COST_TEMP == TRUE)
free (USER_OPTIONS->user_cost_temperature);
if (USER_OPTIONS->DELTA_PARAMETERS == TRUE)
free (USER_OPTIONS->user_delta_parameter);
if (USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
free (USER_OPTIONS->user_quench_param_scale);
if (USER_OPTIONS->QUENCH_COST == TRUE)
free (USER_OPTIONS->user_quench_cost_scale);
if (USER_OPTIONS->RATIO_TEMPERATURE_SCALES == TRUE)
free (USER_OPTIONS->user_temperature_ratio);
free (USER_OPTIONS);
free (parameter_dimension);
free (exit_code);
free (cost_flag);
free (parameter_lower_bound);
free (parameter_upper_bound);
free (cost_parameters);
free (parameter_int_real);
free (cost_tangents);
#if ASA_LIB
return (0);
#else
exit (0);
/* NOTREACHED */
#endif
}
#endif /* SELF_OPTIMIZE */
#if ASA_TEST
/* defines for the test problem, which assume *parameter_dimension
is a multiple of 4. If this is set to a large number, you
likely should set CURVATURE_0 to TRUE. */
#if __GNUC__
/* For _some_ versions of gcc the following may work */
/* #define ARRAY_LIMIT *parameter_dimension */
#define ARRAY_LIMIT 4 /* set equal to *parameter_dimension */
#else
#define ARRAY_LIMIT 4 /* set equal to *parameter_dimension */
#endif
#define ARR_LMT4 (ARRAY_LIMIT/4)
#endif /* ASA_TEST */
/***********************************************************************
* initialize_parameters - sample parameter initialization function
* This depends on the users cost function to optimize (minimum).
* The routine allocates storage needed for asa. The user should
* define the number of parameters and their ranges,
* and make sure the initial parameters are within
* the minimum and maximum ranges. The array
* parameter_int_real should be REAL_TYPE (-1) for real parameters,
* and INTEGER_TYPE (1) for integer values
***********************************************************************/
#if HAVE_ANSI
void
initialize_parameters (double *cost_parameters,
double *parameter_lower_bound,
double *parameter_upper_bound,
double *cost_tangents,
double *cost_curvature,
ALLOC_INT * parameter_dimension,
int *parameter_int_real,
USER_DEFINES * USER_OPTIONS)
#else
void
initialize_parameters (cost_parameters,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
USER_OPTIONS)
double *cost_parameters;
double *parameter_lower_bound;
double *parameter_upper_bound;
double *cost_tangents;
double *cost_curvature;
ALLOC_INT *parameter_dimension;
int *parameter_int_real;
USER_DEFINES *USER_OPTIONS;
#endif
{
ALLOC_INT index;
#if ASA_TEST
/* store the parameter ranges */
for (index = 0; index < *parameter_dimension; ++index)
parameter_lower_bound[index] = -10000.0;
for (index = 0; index < *parameter_dimension; ++index)
parameter_upper_bound[index] = 10000.0;
/* store the initial parameter types */
for (index = 0; index < *parameter_dimension; ++index)
parameter_int_real[index] = REAL_TYPE;
/* store the initial parameter values */
for (index = 0; index < ARR_LMT4; ++index)
{
cost_parameters[4 * (index + 1) - 4] = 999.0;
cost_parameters[4 * (index + 1) - 3] = -1007.0;
cost_parameters[4 * (index + 1) - 2] = 1001.0;
cost_parameters[4 * (index + 1) - 1] = -903.0;
}
/* end ASA_TEST */
#else /* MY_COST */
/* store the parameter ranges */
/* store the initial parameter types */
/* store the initial parameter values */
#endif /* MY_COST */
#if ASA_SAMPLE
#if ASA_TEMPLATE
for (index = 0; index < *parameter_dimension; ++index)
parameter_lower_bound[index] = -1.0;
for (index = 0; index < *parameter_dimension; ++index)
parameter_upper_bound[index] = 1.0;
for (index = 0; index < *parameter_dimension; ++index)
parameter_int_real[index] = REAL_TYPE;
for (index = 0; index < *parameter_dimension; ++index)
cost_parameters[index] = 0.5;
#endif
#endif
/* If USER_INITIAL_PARAMETERS_TEMPS=TRUE, then these must be
defined for all parameters. */
if (USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS == TRUE)
{
if ((USER_OPTIONS->user_parameter_temperature =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_parameter_temperature[index] = 1.0;
}
/* If USER_INITIAL_COST_TEMP=TRUE, then this must be defined. */
if (USER_OPTIONS->USER_INITIAL_COST_TEMP == TRUE)
{
if ((USER_OPTIONS->user_cost_temperature =
(double *) calloc (1, sizeof (double))) == NULL)
exit (9);
USER_OPTIONS->user_cost_temperature[0] = 5.936648E+09;
}
/* If DELTA_PARAMETERS=TRUE, then these must be defined for
all parameters that will be pseudo-differentiated. */
if (USER_OPTIONS->DELTA_PARAMETERS == TRUE)
{
if ((USER_OPTIONS->user_delta_parameter =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_delta_parameter[index] = 0.001;
}
/* If QUENCH_PARAMETERS=TRUE, then these must be defined for
all parameters. */
if (USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
{
if ((USER_OPTIONS->user_quench_param_scale =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_quench_param_scale[index] = 1.0;
}
/* If QUENCH_COST=TRUE, then this must be defined. */
if (USER_OPTIONS->QUENCH_COST == TRUE)
{
if ((USER_OPTIONS->user_quench_cost_scale =
(double *) calloc (1, sizeof (double))) == NULL)
exit (9);
USER_OPTIONS->user_quench_cost_scale[0] = 1.0;
}
/* If RATIO_TEMPERATURE_SCALES=TRUE, then these must be defined
for all parameters. */
if (USER_OPTIONS->RATIO_TEMPERATURE_SCALES == TRUE)
{
if ((USER_OPTIONS->user_temperature_ratio =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_temperature_ratio[index] = 1.0;
}
/* Defines the limit of collection of sampled data by asa */
#if ASA_SAMPLE
/* create memory for bias_generated[] */
if ((USER_OPTIONS->bias_generated =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
#if ASA_TEMPLATE
USER_OPTIONS->limit_weights = 1.0E-7;
if (USER_OPTIONS->QUENCH_COST == TRUE)
USER_OPTIONS->user_quench_cost_scale[0] = 1.0;
if (USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
for (index = 0; index < *parameter_dimension; ++index)
USER_OPTIONS->user_quench_param_scale[index] = 1.0;
#endif
#endif
}
/***********************************************************************
* double cost_function
* This is the users cost function to optimize
* (find the minimum).
* cost_flag is set to true if the parameter set
* does not violates any constraints
* parameter_lower_bound and parameter_upper_bound may be
* adaptively changed during the search.
***********************************************************************/
#if HAVE_ANSI
double
cost_function (double *x,
double *parameter_lower_bound,
double *parameter_upper_bound,
double *cost_tangents,
double *cost_curvature,
ALLOC_INT * parameter_dimension,
int *parameter_int_real,
int *cost_flag,
int *exit_code,
USER_DEFINES * USER_OPTIONS)
#else
double
cost_function (x,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
cost_flag,
exit_code,
USER_OPTIONS)
double *x;
double *parameter_lower_bound;
double *parameter_upper_bound;
double *cost_tangents;
double *cost_curvature;
ALLOC_INT *parameter_dimension;
int *parameter_int_real;
int *cost_flag;
int *exit_code;
USER_DEFINES *USER_OPTIONS;
#endif
{
#if ASA_TEST /* ASA test problem */
/* Objective function from
* %A A. Corana
* %A M. Marchesi
* %A C. Martini
* %A S. Ridella
* %T Minimizing multimodal functions of continuous variables
* with the "simulated annealing" algorithm
* %J ACM Trans. Mathl. Software
* %V 13
* %N 3
* %P 262-279
* %D 1987
*
* This function contains 1.0E20 local minima. When *parameter_dimension
* is equal to 4, visiting each minimum for a millisecond would take
* about the present age of the universe to visit all these minima. */
double d[ARRAY_LIMIT];
double q_n, s_i, t_i, z_i, c_r;
int k_i;
LONG_INT i;
#if SELF_OPTIMIZE
#else
static LONG_INT funevals = 0;
#endif
/* a_i = parameter_upper_bound[i] */
s_i = 0.2;
t_i = 0.05;
c_r = 0.15;
for (i = 0; i < ARR_LMT4; ++i)
{
d[4 * (i + 1) - 4] = 1.0;
d[4 * (i + 1) - 3] = 1000.0;
d[4 * (i + 1) - 2] = 10.0;
d[4 * (i + 1) - 1] = 100.0;
}
q_n = 0.0;
for (i = 0; i < ARRAY_LIMIT; ++i)
{
if (x[i] > 0.0)
{
k_i = (int) (x[i] / s_i + 0.5);
}
else if (x[i] < 0.0)
{
k_i = (int) (x[i] / s_i - 0.5);
}
else
{
k_i = 0;
}
if (fabs (k_i * s_i - x[i]) < t_i)
{
if (k_i < 0)
{
z_i = k_i * s_i + t_i;
}
else if (k_i > 0)
{
z_i = k_i * s_i - t_i;
}
else
{
z_i = 0.0;
}
q_n += c_r * d[i] * z_i * z_i;
}
else
{
q_n += d[i] * x[i] * x[i];
}
}
funevals = funevals + 1;
*cost_flag = TRUE;
#if SELF_OPTIMIZE
#else
#if TIME_CALC
/* print the time every PRINT_FREQUENCY evaluations */
if ((PRINT_FREQUENCY > 0) && ((funevals % PRINT_FREQUENCY) == 0))
{
fprintf (ptr_out, "funevals = %ld ", funevals);
print_time ("", ptr_out);
}
#endif
#endif
return (q_n);
/* end ASA_TEST */
#else /* MY_COST */
/* use the parameter values x[] to define your cost function */
#endif /* MY_COST */
#if ASA_SAMPLE
#if ASA_TEMPLATE
int n, m;
double cost, tmp_dbl;
if (*cost_flag == FALSE)
{
for (m = 0; m < *parameter_dimension; ++m)
{
tmp_dbl = 1.0;
for (n = 0; n < *parameter_dimension; ++n)
{
if (n == m)
continue;
tmp_dbl *= (x[n] * x[n] * (1.0 - x[n] * x[n]));
}
cost_tangents[m] = -tmp_dbl * 2.0 * x[m] * (1.0 - 2.0 * x[m] * x[m]);
}
}
cost = 1.0;
for (n = 0; n < *parameter_dimension; ++n)
{
cost *= (x[n] * x[n] * (1.0 - x[n] * x[n]));
}
*cost_flag = TRUE;
return (-cost);
#endif /* ASA_TEMPLATE */
#endif /* ASA_SAMPLE */
}
/* Here is a good random number generator */
#define SHUFFLE 256 /* size of random array */
#define MULT ((LONG_INT) 25173)
#define MOD ((LONG_INT) 65536)
#define INCR ((LONG_INT) 13849)
#define FMOD ((double) 65536.0)
static LONG_INT seed = 696969;
double random_array[SHUFFLE]; /* random variables */
/***********************************************************************
* double myrand(void) - returns a random number between 0 and 1
* This routine returns the random number generator between 0 and 1
***********************************************************************/
#if HAVE_ANSI
double
myrand (void)
#else
double
myrand ()
#endif
/* returns random number in {0,1} */
{
seed = (LONG_INT) ((MULT * seed + INCR) % MOD);
return ((double) seed / FMOD);
}
/***********************************************************************
* double randflt(void)
* Shuffles random numbers in random_array[]
***********************************************************************/
#if HAVE_ANSI
double
randflt (void)
#else
double
randflt ()
#endif
/* shuffles random numbers in random_array[SHUFFLE] array */
{
/* This RNG is a modified algorithm of that presented in
* %A K. Binder
* %A D. Stauffer
* %T A simple introduction to Monte Carlo simulations and some
* specialized topics
* %B Applications of the Monte Carlo Method in statistical physics
* %E K. Binder
* %I Springer-Verlag
* %C Berlin
* %D 1985
* %P 1-36
* where it is stated that such algorithms have been found to be
* quite satisfactory in many statistical physics applications. */
double rranf;
unsigned kranf;
kranf = (unsigned) (myrand () * SHUFFLE) % SHUFFLE;
rranf = *(random_array + kranf);
*(random_array + kranf) = myrand ();
return (rranf);
}
/***********************************************************************
* initialize_rng()
* This routine initializes the random number generator
***********************************************************************/
#if HAVE_ANSI
void
initialize_rng (void)
#else
void
initialize_rng ()
#endif
{
int n;
double x;
for (n = 0; n < SHUFFLE; ++n)
random_array[n] = myrand ();
for (n = 0; n < 1000; ++n) /* warm up random generator */
x = randflt ();
}
#if USER_COST_SCHEDULE
#if HAVE_ANSI
double
user_cost_schedule (double test_temperature,
USER_DEFINES * USER_OPTIONS)
#else
double
user_cost_schedule (test_temperature,
USER_OPTIONS)
double test_temperature;
USER_DEFINES *USER_OPTIONS;
#endif /* HAVE_ANSI */
{
#if ASA_TEMPLATE
double x;
#if ASA_SAMPLE
#if ASA_TEMPLATE
x = pow (test_temperature, 0.25);
#endif
#else
x = test_temperature;
#endif
return (x);
#endif
}
#endif /* USER_COST_SCHEDULE */
#if USER_REANNEAL_FUNCTION
#if HAVE_ANSI
double
user_reanneal (double current_temp,
double tangent,
double max_tangent,
USER_DEFINES * USER_OPTIONS)
#else
double
user_reanneal (current_temp,
tangent,
max_tangent,
USER_OPTIONS)
double current_temp;
double tangent;
double max_tangent;
USER_DEFINES *USER_OPTIONS;
#endif /* HAVE_ANSI */
{
#if ASA_TEMPLATE
double x;
x = current_temp * (max_tangent / tangent);
return (x);
#endif
}
#endif /* USER_REANNEAL_FUNCTION */
#if SELF_OPTIMIZE
/***********************************************************************
* main
* This is a sample calling program to self-optimize ASA
***********************************************************************/
#if HAVE_ANSI
#if ASA_LIB
int
asa_main ()
#else
int
main (int argc, char **argv)
#endif
#else
#if ASA_LIB
int
asa_main ()
#else
int
main (argc, argv)
int argc;
char **argv;
#endif
#endif
{
#if OPTIONS_FILE
FILE *ptr_options;
char read_option[80];
int read_int;
LONG_INT read_long;
double read_double;
#endif
int *recur_exit_code;
#if ASA_LIB
#else
int compile_cnt;
#endif
double *recur_parameter_lower_bound, *recur_parameter_upper_bound;
double *recur_cost_parameters, *recur_cost_tangents, *recur_cost_curvature;
double recur_cost_value;
ALLOC_INT *recur_parameter_dimension;
int *recur_parameter_int_real;
int *recur_cost_flag;
int recur_v;
USER_DEFINES *RECUR_USER_OPTIONS;
if ((recur_parameter_dimension =
(ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL)
exit (9);
if ((recur_exit_code = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
if ((recur_cost_flag = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
if ((RECUR_USER_OPTIONS =
(USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL)
exit (9);
#if OPTIONS_FILE
ptr_options = fopen ("asa_opt", "r");
#if INT_LONG
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
RECUR_USER_OPTIONS->LIMIT_ACCEPTANCES = read_long;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
RECUR_USER_OPTIONS->LIMIT_GENERATED = read_long;
#else
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->LIMIT_ACCEPTANCES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->LIMIT_GENERATED = read_int;
#endif
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->COST_PRECISION = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->MAXIMUM_COST_REPEAT = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->NUMBER_COST_SAMPLES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->TEMPERATURE_RATIO_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->COST_PARAMETER_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->TEMPERATURE_ANNEAL_SCALE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->USER_INITIAL_COST_TEMP = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->INCLUDE_INTEGER_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS = read_int;
#if INT_ALLOC
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_int;
#else
#if INT_LONG
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%ld", &read_long);
RECUR_USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_long;
#else
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->SEQUENTIAL_PARAMETERS = read_int;
#endif
#endif
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->INITIAL_PARAMETER_TEMPERATURE = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->RATIO_TEMPERATURE_SCALES = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->TESTING_FREQUENCY_MODULUS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->ACTIVATE_REANNEAL = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->REANNEAL_RESCALE = read_double;
fscanf (ptr_options, "%s", read_option);
#if INT_LONG
fscanf (ptr_options, "%ld", &read_long);
#else
fscanf (ptr_options, "%d", &read_long);
#endif
RECUR_USER_OPTIONS->MAXIMUM_REANNEAL_INDEX = read_long;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%lf", &read_double);
RECUR_USER_OPTIONS->DELTA_X = read_double;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->DELTA_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->USER_TANGENTS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->CURVATURE_0 = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->QUENCH_PARAMETERS = read_int;
fscanf (ptr_options, "%s", read_option);
fscanf (ptr_options, "%d", &read_int);
RECUR_USER_OPTIONS->QUENCH_COST = read_int;
fclose (ptr_options);
#else /* OPTIONS_FILE */
RECUR_USER_OPTIONS->LIMIT_ACCEPTANCES = 100;
RECUR_USER_OPTIONS->LIMIT_GENERATED = 1000;
RECUR_USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = 1000;
RECUR_USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = 1.0E-4;
RECUR_USER_OPTIONS->COST_PRECISION = 1.0E-18;
RECUR_USER_OPTIONS->MAXIMUM_COST_REPEAT = 2;
RECUR_USER_OPTIONS->NUMBER_COST_SAMPLES = 2;
RECUR_USER_OPTIONS->TEMPERATURE_RATIO_SCALE = 1.0E-5;
RECUR_USER_OPTIONS->COST_PARAMETER_SCALE = 1.0;
RECUR_USER_OPTIONS->TEMPERATURE_ANNEAL_SCALE = 100.0;
RECUR_USER_OPTIONS->USER_INITIAL_COST_TEMP = FALSE;
RECUR_USER_OPTIONS->INCLUDE_INTEGER_PARAMETERS = FALSE;
RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS = TRUE;
RECUR_USER_OPTIONS->SEQUENTIAL_PARAMETERS = -1;
RECUR_USER_OPTIONS->INITIAL_PARAMETER_TEMPERATURE = 1.0;
RECUR_USER_OPTIONS->RATIO_TEMPERATURE_SCALES = FALSE;
RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS = FALSE;
RECUR_USER_OPTIONS->TESTING_FREQUENCY_MODULUS = 15;
RECUR_USER_OPTIONS->ACTIVATE_REANNEAL = FALSE;
RECUR_USER_OPTIONS->REANNEAL_RESCALE = 10.0;
RECUR_USER_OPTIONS->MAXIMUM_REANNEAL_INDEX = 50000;
RECUR_USER_OPTIONS->DELTA_X = 1.0E-6;
RECUR_USER_OPTIONS->DELTA_PARAMETERS = FALSE;
RECUR_USER_OPTIONS->USER_TANGENTS = FALSE;
RECUR_USER_OPTIONS->CURVATURE_0 = TRUE;
RECUR_USER_OPTIONS->QUENCH_PARAMETERS = FALSE;
RECUR_USER_OPTIONS->QUENCH_COST = FALSE;
#endif /* OPTIONS_FILE */
#if ASA_TEMPLATE
*recur_parameter_dimension = 2;
#endif
if ((recur_parameter_lower_bound =
(double *) calloc (*recur_parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((recur_parameter_upper_bound =
(double *) calloc (*recur_parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((recur_cost_parameters =
(double *) calloc (*recur_parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((recur_parameter_int_real =
(int *) calloc (*recur_parameter_dimension, sizeof (int))
) == NULL)
exit (9);
if ((recur_cost_tangents =
(double *) calloc (*recur_parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if (RECUR_USER_OPTIONS->CURVATURE_0 == FALSE
|| RECUR_USER_OPTIONS->CURVATURE_0 == -1)
{
if ((recur_cost_curvature =
(double *) calloc ((*recur_parameter_dimension)
* (*recur_parameter_dimension),
sizeof (double))) == NULL)
exit (9);
}
else
{
recur_cost_curvature = (double *) NULL;
}
#if OPTIONAL_DATA
/* Set memory to that required for use. */
if ((RECUR_USER_OPTIONS->asa_data =
(double *) calloc (1, sizeof (double))) == NULL)
exit (9);
/* Use asa_data[0] as flag, e.g., if used with SELF_OPTIMIZE. */
RECUR_USER_OPTIONS->asa_data[0] = 0;
#endif
/* open the output file */
ptr_out = fopen ("user_out", "w");
/* use this instead if you want output to stdout */
#if FALSE
ptr_out = stdout;
#endif
fprintf (ptr_out, "%s\n\n", USER_ID);
#if ASA_LIB
#else
/* print out compile options set by user in Makefile */
if (argc > 1)
{
fprintf (ptr_out, "CC = %s\n", argv[1]);
for (compile_cnt = 2; compile_cnt < argc; ++compile_cnt)
{
fprintf (ptr_out, "\t%s\n", argv[compile_cnt]);
}
fprintf (ptr_out, "\n");
}
#endif
#if TIME_CALC
/* print starting time */
print_time ("start", ptr_out);
#endif
fflush (ptr_out);
initialize_rng ();
#if USER_COST_SCHEDULE
RECUR_USER_OPTIONS->cost_schedule = recur_user_cost_schedule;
#endif
#if USER_REANNEAL_FUNCTION
RECUR_USER_OPTIONS->reanneal_function = recur_user_reanneal;
#endif
/* initialize the users parameters, allocating space, etc.
Note that the default is to have asa generate the initial
recur_cost_parameters that satisfy the user's constraints. */
recur_initialize_parameters (recur_cost_parameters,
recur_parameter_lower_bound,
recur_parameter_upper_bound,
recur_cost_tangents,
recur_cost_curvature,
recur_parameter_dimension,
recur_parameter_int_real,
RECUR_USER_OPTIONS);
#if USER_ASA_OUT
if ((RECUR_USER_OPTIONS->asa_out_file =
(char *) calloc (80, sizeof (char))
) == NULL)
exit (9);
#if ASA_TEMPLATE
strcpy (RECUR_USER_OPTIONS->asa_out_file, "asa_sfop");
#endif
#endif
recur_cost_value = asa (recur_cost_function,
randflt,
recur_cost_parameters,
recur_parameter_lower_bound,
recur_parameter_upper_bound,
recur_cost_tangents,
recur_cost_curvature,
recur_parameter_dimension,
recur_parameter_int_real,
recur_cost_flag,
recur_exit_code,
RECUR_USER_OPTIONS);
fprintf (ptr_out, "\n\n recur_cost_value = %g\n",
recur_cost_value);
for (recur_v = 0; recur_v < *recur_parameter_dimension; ++recur_v)
fprintf (ptr_out, "recur_cost_parameters[%d] = %g\n",
recur_v, recur_cost_parameters[recur_v]);
fprintf (ptr_out, "\n\n");
#if TIME_CALC
/* print ending time */
print_time ("end", ptr_out);
#endif
/* close all files */
fclose (ptr_out);
#if OPTIONAL_DATA
free (RECUR_USER_OPTIONS->asa_data);
#endif
#if USER_ASA_OUT
free (RECUR_USER_OPTIONS->asa_out_file);
#endif
#if ASA_SAMPLE
free (RECUR_USER_OPTIONS->bias_generated);
#endif
if (RECUR_USER_OPTIONS->CURVATURE_0 == FALSE
|| RECUR_USER_OPTIONS->CURVATURE_0 == -1)
free (recur_cost_curvature);
if (RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS == TRUE)
free (RECUR_USER_OPTIONS->user_parameter_temperature);
if (RECUR_USER_OPTIONS->USER_INITIAL_COST_TEMP == TRUE)
free (RECUR_USER_OPTIONS->user_cost_temperature);
if (RECUR_USER_OPTIONS->DELTA_PARAMETERS == TRUE)
free (RECUR_USER_OPTIONS->user_delta_parameter);
if (RECUR_USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
free (RECUR_USER_OPTIONS->user_quench_param_scale);
if (RECUR_USER_OPTIONS->QUENCH_COST == TRUE)
free (RECUR_USER_OPTIONS->user_quench_cost_scale);
if (RECUR_USER_OPTIONS->RATIO_TEMPERATURE_SCALES == TRUE)
free (RECUR_USER_OPTIONS->user_temperature_ratio);
free (RECUR_USER_OPTIONS);
free (recur_parameter_dimension);
free (recur_exit_code);
free (recur_cost_flag);
free (recur_parameter_lower_bound);
free (recur_parameter_upper_bound);
free (recur_cost_parameters);
free (recur_parameter_int_real);
free (recur_cost_tangents);
#if ASA_LIB
return (0);
#else
exit (0);
/* NOTREACHED */
#endif
}
/***********************************************************************
* recur_initialize_parameters
* This depends on the users cost function to optimize (minimum).
* The routine allocates storage needed for asa. The user should
* define the number of parameters and their ranges,
* and make sure the initial parameters are within
* the minimum and maximum ranges. The array
* recur_parameter_int_real should be REAL_TYPE (-1)
* for real parameters,
***********************************************************************/
#if HAVE_ANSI
void
recur_initialize_parameters (double *recur_cost_parameters,
double *recur_parameter_lower_bound,
double *recur_parameter_upper_bound,
double *recur_cost_tangents,
double *recur_cost_curvature,
ALLOC_INT * recur_parameter_dimension,
int *recur_parameter_int_real,
USER_DEFINES * RECUR_USER_OPTIONS)
#else
void
recur_initialize_parameters (recur_cost_parameters,
recur_parameter_lower_bound,
recur_parameter_upper_bound,
recur_cost_tangents,
recur_cost_curvature,
recur_parameter_dimension,
recur_parameter_int_real,
RECUR_USER_OPTIONS)
double *recur_parameter_lower_bound;
double *recur_parameter_upper_bound;
double *recur_cost_parameters;
double *recur_cost_tangents;
double *recur_cost_curvature;
ALLOC_INT *recur_parameter_dimension;
int *recur_parameter_int_real;
USER_DEFINES *RECUR_USER_OPTIONS;
#endif
{
ALLOC_INT index;
#if ASA_TEMPLATE
/*
USER_OPTIONS->TEMPERATURE_RATIO_SCALE = x[0];
USER_OPTIONS->COST_PARAMETER_SCALE = x[1];
*/
/* store the initial parameter values */
recur_cost_parameters[0] = 1.0E-5;
recur_cost_parameters[1] = 1.0;
recur_parameter_lower_bound[0] = 1.0E-6;
recur_parameter_upper_bound[0] = 1.0E-4;
recur_parameter_lower_bound[1] = 0.5;
recur_parameter_upper_bound[1] = 3.0;
#endif
/* store the initial parameter types */
for (index = 0; index < *recur_parameter_dimension; ++index)
recur_parameter_int_real[index] = REAL_TYPE;
/* If USER_INITIAL_PARAMETERS_TEMPS=TRUE, then these must be
defined for all parameters. */
if (RECUR_USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS == TRUE)
{
if ((RECUR_USER_OPTIONS->user_parameter_temperature =
(double *) calloc (*recur_parameter_dimension,
sizeof (double))) == NULL)
exit (9);
for (index = 0; index < *recur_parameter_dimension; ++index)
RECUR_USER_OPTIONS->user_parameter_temperature[index] = 1.0;
}
/* If USER_INITIAL_COST_TEMP=TRUE, then this must be defined. */
if (RECUR_USER_OPTIONS->USER_INITIAL_COST_TEMP == TRUE)
{
if ((RECUR_USER_OPTIONS->user_cost_temperature =
(double *) calloc (1, sizeof (double))) == NULL)
exit (9);
RECUR_USER_OPTIONS->user_cost_temperature[0] = 5.936648E+09;
}
/* If DELTA_PARAMETERS=TRUE, then these must be defined for
all parameters that will be pseudo-differentiated. */
if (RECUR_USER_OPTIONS->DELTA_PARAMETERS == TRUE)
{
if ((RECUR_USER_OPTIONS->user_delta_parameter =
(double *) calloc (*recur_parameter_dimension,
sizeof (double))) == NULL)
exit (9);
for (index = 0; index < *recur_parameter_dimension; ++index)
RECUR_USER_OPTIONS->user_delta_parameter[index] = 0.001;
}
/* If QUENCH_PARAMETERS=TRUE, then these must be defined for
all parameters. */
if (RECUR_USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
{
if ((RECUR_USER_OPTIONS->user_quench_param_scale =
(double *) calloc (*recur_parameter_dimension,
sizeof (double))) == NULL)
exit (9);
for (index = 0; index < *recur_parameter_dimension; ++index)
RECUR_USER_OPTIONS->user_quench_param_scale[index] = 1.0;
}
/* If QUENCH_COST=TRUE, then this must be defined. */
if (RECUR_USER_OPTIONS->QUENCH_COST == TRUE)
{
if ((RECUR_USER_OPTIONS->user_quench_cost_scale =
(double *) calloc (1, sizeof (double))) == NULL)
exit (9);
RECUR_USER_OPTIONS->user_quench_cost_scale[0] = 1.0;
}
/* If RATIO_TEMPERATURE_SCALES=TRUE, then these must be defined
for all parameters. */
if (RECUR_USER_OPTIONS->RATIO_TEMPERATURE_SCALES == TRUE)
{
if ((RECUR_USER_OPTIONS->user_temperature_ratio =
(double *) calloc (*recur_parameter_dimension,
sizeof (double))) == NULL)
exit (9);
for (index = 0; index < *recur_parameter_dimension; ++index)
RECUR_USER_OPTIONS->user_temperature_ratio[index] = 1.0;
}
/* Defines the limit of collection of sampled data by asa */
#if ASA_SAMPLE
/* create memory for bias_generated[] */
if ((RECUR_USER_OPTIONS->bias_generated =
(double *) calloc (*recur_parameter_dimension, sizeof (double))
) == NULL)
exit (9);
#if ASA_TEMPLATE
RECUR_USER_OPTIONS->limit_weights = 1.0E-7;
if (RECUR_USER_OPTIONS->QUENCH_COST == TRUE)
RECUR_USER_OPTIONS->user_quench_cost_scale[0] = 1.0;
if (RECUR_USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
for (index = 0; index < *recur_parameter_dimension; ++index)
RECUR_USER_OPTIONS->user_quench_param_scale[index] = 1.0;
#endif
#endif
#if ASA_TEMPLATE
#if ASA_PARALLEL
RECUR_USER_OPTIONS->gener_block = 1;
RECUR_USER_OPTIONS->gener_block_max = 1;
RECUR_USER_OPTIONS->gener_mov_avr = 1;
#endif
#endif
}
/***********************************************************************
* double recur_cost_function
* This is the users cost function to optimize
* (find the minimum).
* cost_flag is set to true if the parameter set
* does not violates any constraints
* recur_parameter_lower_bound and recur_parameter_upper_bound
* may be adaptively changed during the search.
***********************************************************************/
#if HAVE_ANSI
double
recur_cost_function (double *x,
double *recur_parameter_lower_bound,
double *recur_parameter_upper_bound,
double *recur_cost_tangents,
double *recur_cost_curvature,
ALLOC_INT * recur_parameter_dimension,
int *recur_parameter_int_real,
int *recur_cost_flag,
int *recur_exit_code,
USER_DEFINES * RECUR_USER_OPTIONS)
#else
double
recur_cost_function (x,
recur_parameter_lower_bound,
recur_parameter_upper_bound,
recur_cost_tangents,
recur_cost_curvature,
recur_parameter_dimension,
recur_parameter_int_real,
recur_cost_flag,
recur_exit_code,
RECUR_USER_OPTIONS)
double *x;
double *recur_parameter_lower_bound;
double *recur_parameter_upper_bound;
double *recur_cost_tangents;
double *recur_cost_curvature;
ALLOC_INT *recur_parameter_dimension;
int *recur_parameter_int_real;
int *recur_cost_flag;
int *recur_exit_code;
USER_DEFINES *RECUR_USER_OPTIONS;
#endif
{
double cost_value;
static LONG_INT recur_funevals = 0;
int *exit_code;
double *parameter_lower_bound, *parameter_upper_bound;
double *cost_parameters;
double *cost_tangents, *cost_curvature;
ALLOC_INT *parameter_dimension;
int *parameter_int_real;
int *cost_flag;
USER_DEFINES *USER_OPTIONS;
recur_funevals = recur_funevals + 1;
if ((USER_OPTIONS =
(USER_DEFINES *) calloc (1, sizeof (USER_DEFINES))) == NULL)
exit (9);
/* USER_OPTIONS->LIMIT_ACCEPTANCES = 10000; */
USER_OPTIONS->LIMIT_ACCEPTANCES = 1000;
USER_OPTIONS->LIMIT_GENERATED = 99999;
USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = 1000;
USER_OPTIONS->ACCEPTED_TO_GENERATED_RATIO = 1.0E-6;
USER_OPTIONS->COST_PRECISION = 1.0E-18;
USER_OPTIONS->MAXIMUM_COST_REPEAT = 2;
USER_OPTIONS->NUMBER_COST_SAMPLES = 2;
/* USER_OPTIONS->TEMPERATURE_RATIO_SCALE = 1.0E-5; */
USER_OPTIONS->TEMPERATURE_RATIO_SCALE = x[0];
/* USER_OPTIONS->COST_PARAMETER_SCALE = 1.0; */
USER_OPTIONS->COST_PARAMETER_SCALE = x[1];
USER_OPTIONS->TEMPERATURE_ANNEAL_SCALE = 100.;
USER_OPTIONS->USER_INITIAL_COST_TEMP = FALSE;
USER_OPTIONS->INCLUDE_INTEGER_PARAMETERS = FALSE;
USER_OPTIONS->USER_INITIAL_PARAMETERS = FALSE;
USER_OPTIONS->SEQUENTIAL_PARAMETERS = -1;
USER_OPTIONS->INITIAL_PARAMETER_TEMPERATURE = 1.0;
USER_OPTIONS->RATIO_TEMPERATURE_SCALES = FALSE;
USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS = FALSE;
USER_OPTIONS->TESTING_FREQUENCY_MODULUS = 100;
USER_OPTIONS->ACTIVATE_REANNEAL = TRUE;
USER_OPTIONS->REANNEAL_RESCALE = 10.0;
USER_OPTIONS->MAXIMUM_REANNEAL_INDEX = 50000;
USER_OPTIONS->DELTA_X = 0.001;
USER_OPTIONS->DELTA_PARAMETERS = FALSE;
USER_OPTIONS->USER_TANGENTS = FALSE;
USER_OPTIONS->CURVATURE_0 = TRUE;
USER_OPTIONS->QUENCH_PARAMETERS = FALSE;
USER_OPTIONS->QUENCH_COST = FALSE;
if ((parameter_dimension =
(ALLOC_INT *) calloc (1, sizeof (ALLOC_INT))) == NULL)
exit (9);
if ((exit_code = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
if ((cost_flag = (int *) calloc (1, sizeof (int))) == NULL)
exit (9);
#if ASA_TEST
/* set parameter dimension if SELF_OPTIMIZE=TRUE */
*parameter_dimension = 4;
/* end ASA_TEST */
#else /* MY_COST */
/* set parameter dimension if SELF_OPTIMIZE=TRUE */
#endif /* MY_COST */
if ((parameter_lower_bound =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((parameter_upper_bound =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((cost_parameters =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if ((parameter_int_real =
(int *) calloc (*parameter_dimension, sizeof (int))
) == NULL)
exit (9);
if ((cost_tangents =
(double *) calloc (*parameter_dimension, sizeof (double))
) == NULL)
exit (9);
if (USER_OPTIONS->CURVATURE_0 == FALSE || USER_OPTIONS->CURVATURE_0 == -1)
{
if ((cost_curvature =
(double *) calloc ((*parameter_dimension) *
(*parameter_dimension),
sizeof (double))) == NULL)
exit (9);
}
else
{
cost_curvature = (double *) NULL;
}
#if OPTIONAL_DATA
/* Set memory to that required for use. */
if ((USER_OPTIONS->asa_data =
(double *) calloc (2, sizeof (double))) == NULL)
exit (9);
/* Use asa_data[0] as flag, e.g., if used with SELF_OPTIMIZE. */
USER_OPTIONS->asa_data[0] = 1.0;
#endif
#if USER_COST_SCHEDULE
USER_OPTIONS->cost_schedule = user_cost_schedule;
#endif
#if USER_REANNEAL_FUNCTION
USER_OPTIONS->reanneal_function = user_reanneal;
#endif
initialize_parameters (cost_parameters,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
USER_OPTIONS);
/* It might be a good idea to place a loop around this call,
and to average over several values of funevals returned by
trajectories of cost_value. */
funevals = 0;
#if USER_ASA_OUT
if ((USER_OPTIONS->asa_out_file =
(char *) calloc (80, sizeof (char))
) == NULL)
exit (9);
#if ASA_TEMPLATE
strcpy (USER_OPTIONS->asa_out_file, "asa_rcur");
#endif
#endif
cost_value = asa (cost_function,
randflt,
cost_parameters,
parameter_lower_bound,
parameter_upper_bound,
cost_tangents,
cost_curvature,
parameter_dimension,
parameter_int_real,
cost_flag,
exit_code,
USER_OPTIONS);
if (cost_value > .001)
{
*recur_cost_flag = FALSE;
}
else
{
*recur_cost_flag = TRUE;
}
#if FALSE /* set to 1 to activate FAST EXIT */
/* Make a quick exit */
if (recur_funevals >= 10)
{
*recur_cost_flag = FALSE;
RECUR_USER_OPTIONS->LIMIT_INVALID_GENERATED_STATES = 0;
fprintf (ptr_out, "FAST EXIT set at recur_funevals = 10\n\n");
}
#endif
/* print every RECUR_PRINT_FREQUENCY evaluations */
if ((RECUR_PRINT_FREQUENCY > 0) &&
((recur_funevals % RECUR_PRINT_FREQUENCY) == 0))
{
USER_OPTIONS->TEMPERATURE_RATIO_SCALE = x[0];
fprintf (ptr_out, "USER_OPTIONS->TEMPERATURE_RATIO_SCALE = %g\n",
USER_OPTIONS->TEMPERATURE_RATIO_SCALE);
USER_OPTIONS->COST_PARAMETER_SCALE = x[1];
fprintf (ptr_out, "USER_OPTIONS->COST_PARAMETER_SCALE = %g\n",
USER_OPTIONS->COST_PARAMETER_SCALE);
}
#if TIME_CALC
print_time ("", ptr_out);
#endif
fprintf (ptr_out, "recur_funevals = %ld, *recur_cost_flag = %d\n",
recur_funevals, *recur_cost_flag);
/* cost function = number generated at best cost */
#if OPTIONAL_DATA
#if ASA_TEMPLATE
funevals = (LONG_INT) (USER_OPTIONS->asa_data[1]);
fprintf (ptr_out, "\tbest_funevals = %ld, cost_value = %g\n\n",
funevals, cost_value);
/* cost function = total number generated during run */
#endif
#else /* OPTIONAL_DATA */
fprintf (ptr_out, "\tfunevals = %ld, cost_value = %g\n\n",
funevals, cost_value);
#endif
fflush (ptr_out);
#if ASA_SAMPLE
#if ASA_TEMPLATE
#if USER_ASA_OUT
ptr_asa = fopen (USER_OPTIONS->asa_out_file, "r");
#else
ptr_asa = fopen ("asa_out", "r");
#endif
sample (ptr_out, ptr_asa);
#endif
#endif
#if OPTIONAL_DATA
free (USER_OPTIONS->asa_data);
#endif
#if USER_ASA_OUT
free (USER_OPTIONS->asa_out_file);
#endif
#if ASA_SAMPLE
free (USER_OPTIONS->bias_generated);
#endif
if (USER_OPTIONS->CURVATURE_0 == FALSE || USER_OPTIONS->CURVATURE_0 == -1)
free (cost_curvature);
if (USER_OPTIONS->USER_INITIAL_PARAMETERS_TEMPS == TRUE)
free (USER_OPTIONS->user_parameter_temperature);
if (USER_OPTIONS->USER_INITIAL_COST_TEMP == TRUE)
free (USER_OPTIONS->user_cost_temperature);
if (USER_OPTIONS->DELTA_PARAMETERS == TRUE)
free (USER_OPTIONS->user_delta_parameter);
if (USER_OPTIONS->QUENCH_PARAMETERS == TRUE)
free (USER_OPTIONS->user_quench_param_scale);
if (USER_OPTIONS->QUENCH_COST == TRUE)
free (USER_OPTIONS->user_quench_cost_scale);
if (USER_OPTIONS->RATIO_TEMPERATURE_SCALES == TRUE)
free (USER_OPTIONS->user_temperature_ratio);
free (USER_OPTIONS);
free (parameter_dimension);
free (exit_code);
free (cost_flag);
free (parameter_lower_bound);
free (parameter_upper_bound);
free (cost_parameters);
free (parameter_int_real);
free (cost_tangents);
return ((double) funevals);
}
#if USER_COST_SCHEDULE
#if HAVE_ANSI
double
recur_user_cost_schedule (double test_temperature,
USER_DEFINES * RECUR_USER_OPTIONS)
#else
double
recur_user_cost_schedule (test_temperature,
RECUR_USER_OPTIONS)
double test_temperature;
USER_DEFINES *RECUR_USER_OPTIONS;
#endif /* HAVE_ANSI */
{
#if ASA_TEMPLATE
double x;
x = test_temperature;
return (x);
#endif
}
#endif /* USER_COST_SCHEDULE */
#if USER_REANNEAL_FUNCTION
#if HAVE_ANSI
double
recur_user_reanneal (double current_temp,
double tangent,
double max_tangent,
USER_DEFINES * RECUR_USER_OPTIONS)
#else
double
recur_user_reanneal (current_temp,
tangent,
max_tangent,
RECUR_USER_OPTIONS)
double current_temp;
double tangent;
double max_tangent;
USER_DEFINES *RECUR_USER_OPTIONS;
#endif /* HAVE_ANSI */
{
#if ASA_TEMPLATE
double x;
x = current_temp * (max_tangent / tangent);
return (x);
#endif
}
#endif /* USER_REANNEAL_FUNCTION */
#endif /* SELF_OPTIMIZE */
#if ASA_SAMPLE
#if ASA_TEMPLATE
#if HAVE_ANSI
void
sample (FILE * ptr_out, FILE * ptr_asa)
#else
void
sample (ptr_out, ptr_asa)
FILE *ptr_out;
FILE *ptr_asa;
#endif
{
int ind, n_samples, n_accept, index, dim;
double cost, cost_temp, bias_accept;
double param, temp, bias_gener, aver_weight, range;
char ch[80], sample[8];
dim = 2;
n_samples = 0;
fprintf (ptr_out,
":SAMPLE: n_accept cost cost_temp bias_accept \
aver_weight\n");
fprintf (ptr_out,
":SAMPLE: index param[] temp[] bias_gener[] \
range[]\n");
for (;;)
{
fscanf (ptr_asa, "%s", ch);
if (!strcmp (ch, "exit_status"))
{
break;
}
if (strcmp (ch, ":SAMPLE#"))
{
continue;
}
++n_samples;
fprintf (ptr_out, "%s\n", ch);
fflush (ptr_out);
fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
sample, &n_accept, &cost, &cost_temp, &bias_accept, &aver_weight);
if (strcmp (sample, ":SAMPLE+"))
{
fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
}
else
{
fprintf (ptr_out, "%s %10d %12.7g %12.7g %12.7g %12.7g\n",
sample, n_accept, cost, cost_temp, bias_accept, aver_weight);
}
for (ind = 0; ind < dim; ++ind)
{
fscanf (ptr_asa, "%s%d%lf%lf%lf%lf",
sample, &index, ¶m, &temp, &bias_gener, &range);
fprintf (ptr_out, "%s %11d %12.7g %12.7g %12.7g %12.7g\n",
sample, index, param, temp, bias_gener, range);
}
}
fprintf (ptr_out, "\n");
fprintf (ptr_out, "n_samples = %d\n", n_samples);
fflush (ptr_out);
}
#endif /* ASA_TEMPLATE */
#endif /* ASA_SAMPLE */